package com.briup.Server.Impl;

import com.briup.Config.BeanAware;
import com.briup.Config.Impl.SmartConfigImpl;
import com.briup.Config.PropertiesAware;
import com.briup.Config.SmartConfig;
import com.briup.Logger.Impl.LogImpl;
import com.briup.Logger.Log;
import com.briup.Server.Server;
import com.briup.Server.Store.DBStore;
import com.briup.Server.Store.Impl.DBStoreImpl;
import com.briup.entity.Environment;
import org.apache.log4j.Logger;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.*;
/**
 * 服务器端实现步骤
 * > 1. 创建接口实现类实现服务端接口
 * > 2. 实现`Server`接口中未实现的抽象方法`receive`
 * > 3. `receive`方法中主要获取客户端发送过来的Collection<Environment>对象
 * > 4. 新增成员变量标识服务器是否关闭 `boolean isStop`
 * > 5. 创建`ServerSocket`服务器对象，指定端口
 * > 6. 判断服务器是否停止没有停止一直可以接受客户端的连接
 * > 7. 通过`accept`方法接收客户端的连接，获取到Socket对象
 * > 8. 当接收到客户端的连接后，马上开辟子线程完成接收数据的操作
 * > 9. 子线程中通过对象流包装Socket中获取的字节流对象，通过对象输入流读取到客户端发送过来的Collection<Environment>对象
 * > 10. 打印输出获取的Collection<Environment>对象是否与采集的Collection<Environment>对象数据是否一致
 */
public class ServerImpl implements Server, PropertiesAware, BeanAware {
    //private Log log=new LogImpl();
    private Logger log= Logger.getLogger("com.briup.Server.Impl.ServerImpl");

    //定义端口号
    //private int port=9999;
    private int port;

    //定义成员变量，表示服务器开启状态 true:开启  false：关闭
    //private boolean enable=true;//布尔类型存入堆内存默认为false
    private boolean enable;

    private DBStore dbStore;

    @Override
    public Collection<Environment> receive() {
        //接收客户端发送过来的集合数据，返回集合数据
        //声明服务器对象
        ServerSocket serverSocket = null;
        //线程池对象
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        Collection<Environment> environments = new ArrayList<>();
        try {
            serverSocket = new ServerSocket(port);
            log.info("服务器创建成功，等待客户端请求连接！");
            //System.out.println("服务器创建成功，等待客户端请求连接！");
            while (enable) {
                //接收客户端连接 返回值是Socket类型
                Socket socket=serverSocket.accept();
                System.out.println(socket+"客户端连接成功！");

                Callable task=new Callable<Collection<Environment>>() {
                    @Override
                    public Collection<Environment> call() throws Exception {
                        //创建集合对象
                        Collection <Environment> environments=null;
                        //声明流
                        ObjectInputStream ois=null;
                        try {
                            //用客户端对象去读取数据
                            ois = new ObjectInputStream(socket.getInputStream());
                            //读取客户端发送过来的集合对象
                            environments = (Collection<Environment>) ois.readObject();
                            System.out.println("服务器端成功接收到集合对象: " );
                            for (Environment environment : environments) {
                                System.out.println(environment);
                            }
                        } catch (IOException e) {
                            log.error("服务器读取失败");
                        } catch (ClassNotFoundException e) {
                            throw new RuntimeException(e);
                        }finally {
                            if(ois!=null){
                                try {
                                    ois.close();
                                } catch (IOException e) {
                                    throw new RuntimeException(e);
                                }
                            }
                            if(socket!=null){
                                try {
                                    socket.close();
                                } catch (IOException e) {
                                    throw new RuntimeException(e);
                                }
                            }
                        }
                        return environments;
                    }
                };
                //创建FutureTask对象
                FutureTask<Collection<Environment>> futureTask = new FutureTask<Collection<Environment>>(task);
                //提交任务
                executorService.submit(futureTask);
                //获取call方法返回值  集合对象的赋值
                environments.addAll(futureTask.get());
            }
        } catch (Exception e) {
            log.error("连接失败...");
        } finally {
            if(serverSocket!=null){
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return environments;
    }

    @Override
    public void receiveRunable() {
        /**
         * 定义成员变量，表示服务器开启状态 true:开启  false：关闭
         * private boolean enable=true;//布尔类型存入堆内存默认为false
         */
        //声明服务器对象
        ServerSocket serverSocket = null;
        //线程池对象
        //ExecutorService executorService= Executors.newFixedThreadPool(10);
        try {
            //创建服务器对象
            serverSocket=new ServerSocket(port);
            log.info("服务器启动成功，等待客户端连接......");
            //服务器开启
            while(enable){
                Socket socket=serverSocket.accept();
                System.out.println("客户端连接成功，IP："+socket.getInetAddress()+"连接成功！");

                Runnable runnable=new Runnable(){
                    @Override
                    public void run() {
                        log.info("开始接收数据...");
                        ObjectInputStream ois = null;
                        try {
                            //创建流
                            ois = new ObjectInputStream(socket.getInputStream());
                            //读取从客户端发来的集合对象
                            Collection<Environment> environments=(Collection<Environment>) ois.readObject();
                            System.out.println("从客户端接收了"+environments.size()+"条数据");

//                            //创建入库模块对象
//                            DBStore dbStore = new DBStoreImpl();

                            log.info("准备入库....");
                            //入库
                            dbStore.saveDBStore(environments);

                        } catch (Exception e) {
                            e.printStackTrace();
                            log.error("服务器故障！");
                        } finally {
                            if(ois!=null){
                                try {
                                    ois.close();
                                } catch (IOException e) {
                                    log.error("关闭失败！");
                                }
                            }
                            if(socket!=null){
                                try {
                                    socket.close();
                                } catch (IOException e) {
                                    log.error("关闭失败！");
                                }
                            }
                        }
                    }
                };
                Thread th=new Thread(runnable);
                th.start();

            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            if(serverSocket!=null){
                try {
                    Thread.sleep(1000);
                    serverSocket.close();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
    @Override
    //跳出while循环，服务器关闭
    public void closeServer() {
        System.out.println("服务器即将关闭...");
        enable=false;
    }

    @Override
    public void setProperties() {
        enable = Boolean.parseBoolean((String) SmartConfigImpl.getPropertiesMap().get("enable"));
        port = Integer.parseInt((String) SmartConfigImpl.getPropertiesMap().get("port"));

    }

    @Override
    public void setBean(SmartConfig smartConfig) {
        dbStore = smartConfig.getDBStore();
    }
}
